#pragma once
#include"room.hpp"

class session
{
public:
    session(int sid,int uid,bool islogin)
    :_sid(sid)
    ,_uid(uid)
    ,_islogin(islogin)
    {

    }

    ~session()
    {

    }

    int get_sid()
    {
        return _sid;
    }

    int get_uid()
    {
        return _uid;
    }

    void set_islogin(bool islogin)
    {
        _islogin = islogin;
    }
    
    bool is_login()
    {
        return _islogin;
    }

    void set_timer(wsserver_t::timer_ptr tp)
    {
        _tp = tp;
    }

    wsserver_t::timer_ptr get_timer()
    {
        return _tp;
    }
   

private:
    int _sid;
    int _uid;
    bool _islogin;
    wsserver_t::timer_ptr  _tp;
};

using session_ptr = std::shared_ptr<session>;

class session_manager
{
public:
    session_manager(wsserver_t* server)
    :_nextsid(1)
    ,_server(server)
    {

    }

    ~session_manager()
    {

    }

    session_ptr create_session(int uid,bool islogin)
    {
        std::lock_guard<std::mutex> lg(_mutex);
        session_ptr sp(new session(_nextsid,uid,islogin));
        _sidtos.insert(std::make_pair(_nextsid,sp));
        ++_nextsid;
        return sp;
    }   

    session_ptr get_session_by_sid(int sid)
    {
        std::lock_guard<std::mutex> lg(_mutex);
        auto it = _sidtos.find(sid);
        if(it == _sidtos.end())
        {
            return session_ptr();
        }
        return it->second;
    }

    void remove_session(int sid)
    {
        std::lock_guard<std::mutex> lg(_mutex);
        _sidtos.erase(sid);
    }

    void repeat_insert(session_ptr sp)
    {
        std::lock_guard<std::mutex> lg(_mutex);
        _sidtos.insert(std::make_pair(sp->get_sid(),sp));
    }

    //ms == -1 代表session永久有效
    void set_session_timer(int sid,int ms)
    {
        session_ptr sp = get_session_by_sid(sid);
        if(sp.get() == nullptr)
        {
            return;
        }
        wsserver_t::timer_ptr tp = sp->get_timer();
        if(tp.get() == nullptr &&  ms == -1)
        {
            //本就永久有效，不需操作
        }
        else if(tp.get() == nullptr && ms != -1)
        {
            wsserver_t::timer_ptr temp = _server->set_timer(ms,std::bind(&session_manager::remove_session,this,sid));
            sp->set_timer(temp);
        }
        else if(tp.get() != nullptr && ms == -1)
        {
            tp->cancel();
            sp->set_timer(wsserver_t::timer_ptr());
            _server->set_timer(0,std::bind(&session_manager::repeat_insert,this,sp));
        }
        else //tp.get() != nullptr && ms != -1
        {   
            tp->cancel();
            _server->set_timer(0,std::bind(&session_manager::repeat_insert,this,sp));
            wsserver_t::timer_ptr temp = _server->set_timer(ms,std::bind(&session_manager::remove_session,this,sid));
            sp->set_timer(temp);
        }
    }   

private:
    int _nextsid;
    std::mutex _mutex;
    std::unordered_map<int,session_ptr> _sidtos;
    wsserver_t* _server;
};  